package com.jrauto.CarAppBackend.service;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.model.*;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author : huiMing
 * Date : 2025年07月02日 14:02
 * @version V1.0
 */
@Service
public class CosService {

    @Resource
    private COSClient cosClient;

    @Value("${tencent.cos.bucketName}")
    private String bucketName;

    @Value("${tencent.cos.folder}")
    private String folder;

    @Value("${tencent.cos.webUrl}")
    private String webUrl;

    /**
     * 上传文件到 COS。
     * @param file 要上传的 MultipartFile 对象。
     * @return 上传文件在 COS 上的访问 URL。
     * @throws IOException 如果发生 I/O 错误。
     * @throws RuntimeException 如果 COS 服务或客户端发生异常。
     */
    public String uploadFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件内容不能为空。");
        }

        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.lastIndexOf(".") != -1) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String fileName = UUID.randomUUID().toString() + fileExtension;
        String cosKey = folder + fileName;

        try (InputStream inputStream = file.getInputStream()) {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(file.getSize());
            objectMetadata.setContentType(file.getContentType());

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, cosKey, inputStream, objectMetadata);
            cosClient.putObject(putObjectRequest);
            return webUrl + cosKey;


        } catch (CosServiceException e) {
            e.printStackTrace();
            throw new RuntimeException("COS 服务异常，上传文件失败: " + e.getErrorMessage());
        } catch (CosClientException e) {
            e.printStackTrace();
            throw new RuntimeException("COS 客户端异常，上传文件失败: " + e.getMessage());
        }
    }

    /**
     * 从 COS 删除文件。
     * @param fileUrl 要删除文件的完整 URL。
     * @return true 如果删除成功，否则返回 false。
     */
    public boolean deleteFile(String fileUrl) {
        if (fileUrl == null || fileUrl.isEmpty()) {
            return false;
        }
        // 从完整 URL 中提取 COS Key。假设 URL 格式为：webUrl + cosKey
        String cosKey = fileUrl.replace(webUrl, "");
        // 确保 cosKey 是有效的，例如检查是否以配置的 folder 开头
        if (!cosKey.startsWith(folder) && !folder.equals("/")) { // 如果 folder 是根目录，则不需要严格检查
            System.err.println("尝试删除不在配置 COS 文件夹内的文件或 URL 格式不匹配: " + fileUrl);
            // 也可以根据实际情况抛出异常
            return false;
        }

        try {
            cosClient.deleteObject(bucketName, cosKey);
            System.out.println("成功删除COS文件: " + cosKey);
            return true;
        } catch (CosServiceException e) {
            e.printStackTrace();
            System.err.println("COS 服务异常，删除文件失败: " + e.getErrorMessage());
            return false;
        } catch (CosClientException e) {
            e.printStackTrace();
            System.err.println("COS 客户端异常，删除文件失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从 COS 下载文件到本地指定路径。
     * @param cosKey 文件的 COS Key。
     * @param localFilePath 文件在本地保存的完整路径。
     * @return true 如果下载成功，否则返回 false。
     * @throws IllegalArgumentException 如果 COS Key 或本地路径为空。
     */
    public boolean downloadFile(String cosKey, String localFilePath) {
        if (cosKey == null || cosKey.isEmpty() || localFilePath == null || localFilePath.isEmpty()) {
            throw new IllegalArgumentException("COS Key 和本地文件路径不能为空。");
        }

        File downloadFile = new File(localFilePath);
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, cosKey);

        try {
            cosClient.getObject(getObjectRequest, downloadFile);
            return true;
        } catch (CosServiceException e) {
            e.printStackTrace();
            return false;
        } catch (CosClientException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 生成 COS 对象的预签名 URL。
     * @param cosKey COS 中的对象 Key。
     * @param expirationTimeInMinutes URL 的有效时间（分钟）。
     * @return 预签名 URL 字符串。
     */
    public String generatePresignedUrl(String cosKey, int expirationTimeInMinutes) {
        Date expiration = new Date(System.currentTimeMillis() + 1000L * 60 * expirationTimeInMinutes);
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, cosKey, HttpMethodName.GET);
        req.setExpiration(expiration);
        URL url = cosClient.generatePresignedUrl(req);
        return url.toString();
    }

    /**
     * 列出指定 COS 文件夹内的对象。
     * @param prefix 要列出的对象前缀。
     * @return 包含对象元数据的 COSObjectSummary 列表。
     * @throws RuntimeException 如果 COS 服务或客户端发生异常。
     */
    public List<COSObjectSummary> listObjects(String prefix) {
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
        listObjectsRequest.setBucketName(bucketName);
        if (prefix != null && !prefix.isEmpty()) {
            listObjectsRequest.setPrefix(prefix);
        }

        ObjectListing objectListing = null;
        try {
            objectListing = cosClient.listObjects(listObjectsRequest);
            return objectListing.getObjectSummaries();
        } catch (CosServiceException e) {
            e.printStackTrace();
            throw new RuntimeException("COS 服务异常，列出对象失败: " + e.getErrorMessage());
        } catch (CosClientException e) {
            e.printStackTrace();
            throw new RuntimeException("COS 客户端异常，列出对象失败: " + e.getMessage());
        }
    }
}
